#!/bin/bash

#
# sshtmpl -- by Dario Berzano <dario.berzano@gmail.com>
#
# Part of the lfscripts suite -- http://lfscripts.googecode.com/
#
# Generates a SSH configuration file (i.e., ~/.ssh/config) from a given template
# written in Cheetah: http://www.cheetahtemplate.org/
#

SshDir="$HOME/.ssh"
SshConfigFile="$SshDir/config"

Tmp=`mktemp /tmp/cheetah-ssh-XXXXX`
Cheetah=cheetah

[ "$1" == '' ] && SshConfig='default' || SshConfig="$1"
export SshConfig

# Backup old configuration file
echo "Using configuration: $SshConfig" >&2
if [ -e "$SshConfigFile" ] ; then
  echo "Making a backup: $SshConfigFile -> $SshConfigFile.bak" >&2
  mv "$SshConfigFile" "$SshConfigFile".bak
fi

# Add Cheetah header to template
cat >> $Tmp <<_EOF_
##
## Get SSH configuration name from the definition; use 'default' if undefined
##

#set global \$SshConfig = \$getVar('SshConfig', 'default')
#set global \$AutoPort = 20000
#set global \$LocalFwd = []

##
## Defines pairs of host[:port] for each reachable host. Use 'auto' instead of
## the port number to auto-assign a port for local forwarding
##

#def HostPort(\$List)

  #set \$Host = ''
  #set \$Port = -1
  #set \$DefHost = ''
  #set \$DefPort = -1

  #for \$Pair in \$List.items()

    ## Search for a host[:port] pair matching current configuration. If no
    ## matching pair is found, revert to a default configuration

    #if \$Pair[0] == \$SshConfig
      #set \$Hp = \$Pair[1].split(':')
      #set \$Host = \$Hp[0]
      #if \$len(\$Hp) > 1
        #if \$Hp[1] == 'auto'
          #set global \$AutoPort+=1
          #set \$Port = \$AutoPort
        #else
          #set \$Port = \$Hp[1]
        #end if
      #else
        #set \$Port = 22
      #end if
    #end if

    ## Set default host and port. A default configuration must always exist

    #if \$Pair[0] == 'default'
      #set \$Hp = \$Pair[1].split(':')
      #set \$DefHost = \$Hp[0]
      #if \$len(\$Hp) > 1
        #set \$DefPort = \$Hp[1]
      #else
        #set \$DefPort = 22
      #end if
    #end if

  #end for

  ## If no 'default' configuration exists, output a comment describing the error

  #if \$DefPort == -1
    # Warning: no host[:port] pair for 'default' configuration on this host!
    #stop
  #end if

  ## If no host[:port] exist for this configuration, revert to 'default' ones
  #if \$Port == -1
    # No host[:port] for configuration '\$SshConfig': using 'default' ones
    #set \$Host = \$DefHost
    #set \$Port = \$DefPort
  #end if

  ## Append to the list of local forwards
  #if \$SshConfig != 'default' and \$Host == 'localhost'
    #silent \$LocalFwd.append( [ \$Port, \$DefHost, \$DefPort ] )
    CheckHostIP no
  #end if

  ## Output host name
  HostName \$Host

  ## Output port, if non-standard (different from 22)
  #if \$Port != 22
    Port \$Port #slurp
  #end if

#end def

##
## Base port
##

#def BasePort(\$List)
  #for \$Pair in \$List.items()
    #if \$Pair[0] == \$SshConfig
      #set global \$AutoPort = \$Pair[1]
    #end if
  #end for
#end def

##
## Output all the local forwards added to the list as LocalForward directives
##

#def LocalForwardList()
#for \$Fwd in \$LocalFwd
  LocalForward \$Fwd[0] \$Fwd[1]:\$Fwd[2]
#end for
#end def

_EOF_
cat "$SshConfigFile".tmpl >> $Tmp

# Invoke Cheetah
"$Cheetah" fill --env $Tmp --nobackup --oext cf > /dev/null

if [ $? == 0 ] ; then

  Perl='if ($_ =~ /^\s*$/) {}'
  Perl="$Perl "'elsif ($_ =~ /^\s+(.*)$/) { print "  $1\n" }'
  Perl="$Perl "'elsif ($_ =~ /^(Host.*)$/) { print "\n$1\n" }'
  Perl="$Perl "'else { print "$_" }' 

  # Header
  cat > "$SshConfigFile" <<_EOF_
#
# This file was automatically generated by Cheetah: it is pointless to edit it.
#
# You can edit the originating template instead:
#   $SshConfigFile.tmpl
#
# SSH configuration in use: $SshConfig
#
# Generated: `LC_ALL=C date`
#

_EOF_

  # Nice output
  cat $Tmp.cf | perl -ne "$Perl" >> "$SshConfigFile"

  # Remove on success
  echo "Generated: $SshConfigFile"
  rm -f $Tmp $Tmp.cf

else
  echo "Error when generating SSH configuration from $SshConfigFile" >&2
  rm -f $Tmp $Tmp.cf
  exit 1
fi
